#pragma once
#include "ThreadPool.h"
#include "ThreadSemaphore.h"
#include "SharedPtr.h"
#include "CommType.h"
#include "List.h"

namespace COMM
{
	class Task;
	class COMM_API TaskResult
	{
	private:
		friend class Task;
		CommType m_result;
		ThreadSemaphore m_sem;
	public:
		bool Join(CommType* result = NULL, unsigned int timeoutMs = -1);
	};

#ifdef COMM_MSVC
	template class COMM_API SharedPtr<TaskResult>;
#endif
	class COMM_API TaskItem
	{
	private:
		friend class Task;
		SharedPtr<TaskResult> m_feedback;
	public:
		TaskItem();
		virtual ~TaskItem() {}
		virtual void Release() { delete this; }
		virtual CommType Do() = 0;
	};

#ifdef COMM_MSVC
	template class COMM_API stdlist<TaskItem*>;
	template class COMM_API List<TaskItem*>;
#endif
	class COMM_API Task : private ThreadPool
	{
	public:
		Task(int threadsCount = ThreadPool::DefaultThreadsCount, const char* taskName = NULL);
		~Task(void);
		// overwrite.
		void Start();
		void Stop(bool cancelThread=false);

		int Count();
		SharedPtr<TaskResult> Schedule(TaskItem* item);
		typedef CommType (*WorkProc)(CommType& arg);
		SharedPtr<TaskResult> Schedule(WorkProc proc, const CommType& arg = CommType::Null);
		
	protected:
		virtual int Process(int index);
	private:
		List<TaskItem*> m_itemList;
		ThreadSemaphore m_sem;
		AtomInt m_running;
	};

#ifdef COMM_MSVC
	template class COMM_API SharedPtr<TaskResult>;
	template class COMM_API stdlist<TaskItem*>;
	template class COMM_API List<TaskItem*>;
#endif
}


